#!/usr/local/bin/python3
# #!/usr/bin/python3
# -*- coding: utf-8 -*-


import os
import datetime
from flask import Flask, render_template, request, redirect, url_for, session, make_response, jsonify
import re
import json
import qastutil


app = Flask(__name__)

nowstr =  lambda: datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")

# base path
bpath = "/"

# JD 2450000.5
day0 = datetime.datetime.strptime("1995-10-10T08:00", "%Y-%m-%dT%H:%M")
mjd0 = 50000
nowmjd = lambda: (datetime.datetime.now() - day0).total_seconds() / 86400.0 + mjd0


class telinfo():
    """望远镜信息"""
    def __init__(self, line="||||"):
        pp = line.split("|")
        self.id   = int(pp[0].strip())
        self.tel  = pp[1].strip()
        self.pswd = pp[2].strip()
        self.lon = float(pp[3].strip().split(",")[0].strip())
        self.lat = float(pp[3].strip().split(",")[1].strip())
        self.name = pp[4].strip()
        self.term = [t.strip() for t in pp[5].split(",") if t]
        self.op   = [t.strip() for t in pp[6:]]

    def __repr__(self):
        return "|".join([f"{self.id:03d}", self.tel, self.pswd, self.name, ",".join(self.term)] + self.op)


def loadtel():
    """加载数据"""
    # 读入望远镜文件
    dat_file="cell/tel.txt"
    teltxt = open(dat_file, encoding="UTF-8").readlines()
    tels = [telinfo(t) for t in teltxt]
    tels.sort(key=lambda g:g.id)
    return tels


def checktel(tels, tel, pswd):
    """逐个验证，检验账号密码是否属于某台望远镜"""
    tt = None
    for t in tels:
        if t.tel == tel and t.pswd == pswd:
            tt = t
            break
    return tt


def tstatus(tel, line="||||"):
    """状态信息"""
    pp = line.split("|")
    s = {}
    s["tel"   ] = tel
    s["time"  ] = pp[0].strip()
    s["status"] = pp[1].strip()
    s["term"  ] = pp[2].strip()
    s["op"    ] = pp[3].strip()
    s["ip"    ] = pp[4].strip()
    return s


def loadstatus(t):
    """加载状态数据"""
    tel = t.tel
    # 读入状态文件
    if os.path.isfile(f"cell/{tel}.txt"):
        statustxt = open(f"cell/{tel}.txt", "r", encoding="UTF-8").readlines()
        # 按时间倒序排序
        statustxt.sort(reverse=True)
        status = [tstatus(tel, s) for s in statustxt]
        # 判断是否白天
        mjd = nowmjd()
        sun_ra, sun_de, _, _ = qastutil.sun_pos(mjd)
        lst = qastutil.lst(mjd, t.lon)
        sun_az, sun_alt = qastutil.azalt(t.lat, lst, sun_ra, sun_de)
        print(f"{t.tel} MJD={mjd:9.3f} LST{lst:6.3f} Sun{sun_ra:7.3f}{sun_de:+7.3f} AZALT{sun_az:7.3f}{sun_alt:+7.3f}")
        if sun_alt > -6:
            status.insert(0, tstatus(tel, "NOW|day|-|-|-"))
        if not status:
            status = [None]
    else:
        status = [None]
    return status


def addstatus(tel, status, term, opinfo, ip):
    """追加状态"""
    with open(f"cell/{tel}.txt", "a", encoding="UTF-8") as ff:
        ff.write(f"{nowstr()} | {status} | {term} | {opinfo} | {ip}\n")


@app.route("/", methods=["GET"])
def home():
    """显示登录页面"""
    res = make_response(render_template(
        "login.html", err=0))
    return res


@app.route("/", methods=["POST"])
def login():
    """登录验证"""
    # 从表单读输入的账号密码
    tel  = request.form.get("tel", "")
    pswd = request.form.get("pswd", "")
    # 加载全部望远镜列表
    tels = loadtel()
    tt = checktel(tels, tel, pswd)
    
    # 望远镜状态字典
    statusall = json.dumps(
        {"ok":"可用", "l0":"零级可用", "l1":"一级可用", "l2":"二级可用", "no":"不可用", "in":"ToO观测", "day":"白天",}, 
        ensure_ascii=False)
    statusnote = json.dumps({
            "ok":"允许接受ToO观测调度",
            "l0":"允许接受ToO观测调度",
            "l1":"允许接受ToO观测调度",
            "l2":"允许接受ToO观测调度",
            "no":"不接受ToO调度，原因可能是天气不好、设备状态不适合、当前任务优先级高或其他",
            "in":"已经接受调度，正在执行中",
            "day":"白天",
        }, ensure_ascii=False)
        
    if tt and tt.id >= 900:
        # 如果是查看账号，转查看页面，显示账号密码
        telall = {t.tel:t.name for t in tels if t.id < 900}
        telall = json.dumps(telall, ensure_ascii=False)
        res = make_response(render_template(
            "watch.html", tel=tel, pswd=pswd, telall=telall, 
                          statusall=statusall, statusnote=statusnote))
            
    elif tt:
        term = json.dumps(tt.term, ensure_ascii=False)
        op = json.dumps(tt.op, ensure_ascii=False)
        res = make_response(render_template(
            "tel.html", tel=tel, pswd=pswd, tname=tt.name, op=op, term=term, 
                        statusall=statusall, statusnote=statusnote))
    else:
    
        res = make_response(render_template(
            "login.html", err=1))
    return res


@app.route("/news", methods=["POST"])
def news():
    """获取各望远镜最新的状态"""
    # 从表单读输入的账号密码
    tel  = request.form.get("tel", "")
    pswd = request.form.get("pswd", "")
    # 加载全部望远镜列表
    tels = loadtel()
    tt = checktel(tels, tel, pswd)
    # 逐个加载并显示最新的状态
    if tt and tt.id > 900:
        status = [loadstatus(t)[0] for t in tels]
    elif tt:
        status = [loadstatus(t)[0] for t in tels if t.tel == tel]
    else:
        status = []
    # 删除无状态的望远镜
    status = [s for s in status if s]

    res = json.dumps(status, indent=2, ensure_ascii=False)
    return res    


@app.route("/last", methods=["POST"])
def last():
    """获取望远镜的历史状态"""
    # 从表单读输入的账号密码
    tel  = request.form.get("tel", "")
    pswd = request.form.get("pswd", "")
    show = request.form.get("show", "")
    # 加载全部望远镜列表
    tels = loadtel()
    tt = checktel(tels, tel, pswd)
    # 逐个加载并显示最新的状态
    if tt and tt.id > 900:
        status = [loadstatus(t) for t in tels if t.tel == show]
    elif tt:
        status = [loadstatus(t) for t in tels if t.tel == tel]
    else:
        # 登录错误，或者想查看别的望远镜的数据
        status = []
    if status:
        status = status[0]
    status = [s for s in status if s]

    res = json.dumps(status, indent=2, ensure_ascii=False)
    return res


@app.route("/report", methods=["POST"])
def report():
    """更新望远镜状态"""
    tel  = request.form.get("tel", "")
    pswd = request.form.get("pswd", "")
    term = request.form.get("term", "")
    status = request.form.get("status", "")
    opinfo = request.form.get("opinfo", "")
    ip = request.remote_addr
    # 加载全部望远镜列表
    tels = loadtel()
    tt = checktel(tels, tel, pswd)
    # 更新状态，只有望远镜能更新
    if tt:
        addstatus(tel, status, term, opinfo, ip)
        res = "OK"
    else:
        res = "FAIL"
    return res


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=24311, debug=True)
